#ifndef SimulateBASE_H
#define SimulateBASE_H

#include "circuit.h"
#include <fstream>
#include <list>
#include <map>
#include <set>
#include <stdlib.h>
#include <math.h>
#include "pareto.h"

typedef struct resMap_{
        int DFF_id;
        set<int> R0;
        set<int> R1;
        set<int> Overlap;
        double P0;
        double P1;
}resMap;

class Simulate{
  public:
        ~Simulate();
  Simulate(Circuit *C):Ci(C) {}
        
        double huerSelect2Process(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces);
        double simSelect(const int trace_size);
        bool simHybrid(void);
        bool simHybrid1Trace(bool test);
        void initSimulateHybrid();
        void initSimulate(void);
        void initSimulate(bool);
        void initSimulateGolden(void);
        void setSigValues(vector<Signal *> sigs, vector<Value> vals);
        void setTraceValues(vector<Value> vals);
        bool sim1cycle(void);
        bool sim1cycleBackward(void);
        bool sim1cycleExh(void);
        void simNcycle(int n);
        void sim_event(bool);
        void sim_event_cycle(void);
        bool sim_event_cycle1(void);
        bool sim_event_back_cycle1(void);
        bool simAllCycle();
        void simNcycleBackward(int n);
        bool simAllCycleBackward();
        void dump(void);
        void dumpOutput(void);
        void forwardSimReg(int n);
        void forwardSim_event(int n);
        void forwardGolden(int n);
        void backwardSimReg(void);
        void setResets(void);
        void simTraced(int cn);
        void hueristicSelect(const char* filename, const int trace_size);
        void hueristicSelect2(const int trace_size, const char* filename);
        double computVN(char *filename);
        double computVN();
        void printTraced(){
                for(int i = 0; i < tracedSigs.size(); i++)
                        cout<<tracedSigs[i]->getName()<<"\t";
                cout << endl;
        }
        void initGates(void);
        
        void clearTraced()
        { 
                tracedSigs.clear();
        }
        
        Signal* getTraced(int i) {return tracedSigs[i];}
        void addTraced(Signal* s) {tracedSigs.push_back(s);}
        int tracedSize(void) {return tracedSigs.size();}
	
        Circuit *Ci;
        vector<Node*> passive;
        vector<Signal*> tracedSigs;
        
  protected:
        vector<Node*> passiveGates;
        ofstream dumpFile;
};

/*
struct longSequence : public binary_function<map<int, set<int> >::iterator, map<int, set<int> >::iterator, bool> {
        bool operator()(map<int, set<int> >::iterator it_a, map<int, set<int> >::iterator it_b){
                return ((*it_a).second.size() > (*it_b).second.size());
        }
};
*/

#endif
